/// ref: https://doc.rust-lang.org/nomicon/subtyping.html
/// ref: https://oswalt.dev/2020/07/rust-traits-defining-behavior/
/// 使用特性实际上解决的是类继承的问题，但是特性和类继承还是有很大区别的，但是对于从传统语言过来的人都会有这样的想法

pub trait AnimalTrait {
  fn eat(&self);
  fn get(&self) -> &Self
  where
    Self: Sized;
  fn get_pure(&self) -> Self
  where
    Self: Sized;
  fn get_clone(&self) -> Self
  where
    Self: Sized;
}

pub trait CatTrait: AnimalTrait {
  fn mmm(&self);
}

pub trait DogTrait: AnimalTrait {
  fn www(&self);
}

#[derive(Copy, Clone)]
pub struct Animal {}

impl AnimalTrait for Animal {
  fn eat(&self) {
    println!("`eat(&self)`");
  }
  fn get(&self) -> &Self {
    return &self;
  }
  fn get_pure(&self) -> Self {
    return *self;
  }
  fn get_clone(&self) -> Self {
    return Animal {};
  }
}

// #[derive(Copy, Clone)]
pub struct Cat {}

impl CatTrait for Cat {
  fn mmm(&self) {
    println!("`mmm(&self)`");
  }
}
impl Copy for Cat {}

impl Clone for Cat {
  fn clone(&self) -> Self {
    Self {}
  }
}

impl AnimalTrait for Cat {
  fn eat(&self) {
    println!("`Cat eat(&self)`");
  }
  fn get(&self) -> &Self {
    return &self;
  }
  fn get_pure(&self) -> Self {
    return *self;
  }
  fn get_clone(&self) -> Self {
    return Cat {};
  }
}

#[derive(Copy, Clone)]
pub struct Dog {}

impl DogTrait for Dog {
  fn www(&self) {
    println!("`www(&self)`");
  }
}

impl AnimalTrait for Dog {
  fn eat(&self) {
    println!("`Dog eat(&self)`");
  }
  fn get(&self) -> &Self {
    return &self;
  }
  fn get_pure(&self) -> Self {
    return *self;
  }
  fn get_clone(&self) -> Self {
    return Clone::clone(&self);
  }
}

#[cfg(test)]
mod tests {
  #[test]
  fn test_1() {
    use crate::trait_demo::*;
    let mut list = Vec::<Box<dyn AnimalTrait>>::new();
    list.push(Box::new(Animal {}));
    list.push(Box::new(Cat {}));
    list.push(Box::new(Dog {}));
    for elem in list {
      elem.eat();
    }
  }
}



